package server_commands;

import static server.RLM_Server.activeConnections;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

import server.ServerSocketConnection;
import utils.NetworkUtils;
import connection_modul.DatabaseConnection;

/**
 * Konkretizacija apstraktne klase Command koja sluzi za procesuiranje komande logovanja.
 *  
 * @author Uros Krkic & Martin Jondzic
 *
 */
public class LOGINCommand extends Command {

	
	public LOGINCommand(String parameter) {
		setCode(LOGIN_CMD);
		setParameter(parameter);
	}
	
	/**
	 * Procesuira se komanda logovanja. Najpre se proverava da li je korisnik logovan i 
	 * u tom slucaju se ne dozvoljava dalje logovanje. Ukoliko je sve u redu vrsi se
	 * upis novih podataka, primljenih od strane korisnika, u bazu i obavestavaju
	 * se korisnici na cijim je listama o logovanju.
	 * 
	 * @param connection - konekcija ka klijentu
	 * @param dbConnection - objekat za rad sa bazom
	 */
	public boolean executeCommand(ServerSocketConnection connection, DatabaseConnection dbConnection) {

		StringTokenizer tokenizer = new StringTokenizer(getParameter());
		
		String username = tokenizer.nextToken().toLowerCase();
		String password = tokenizer.nextToken();
		String status = tokenizer.nextToken();
		String localAddress = tokenizer.nextToken();
//		String ip_address = tokenizer.nextToken();
		String port = tokenizer.nextToken();
		
		String ip_address = NetworkUtils.getIPFromSockeAddress( connection.getSocket().getRemoteSocketAddress() );
		
		try {
			dbConnection.doStatement("SELECT * FROM tblUsers WHERE username = " +
									 "'" + username + "'");
		
			if ( dbConnection.data.size() == 0 ) {
				connection.setMessage("210 Bad username");
				dbConnection.doCommit();
				return true;
			}
			
			Vector row = dbConnection.data.get(0);
			
			if ( !row.get(7).toString().equalsIgnoreCase("Offline") ) {
				connection.setMessage("220 User already logged");
				dbConnection.doCommit();
				return true;
			}
				
			
			String pass = dbConnection.data.get(0).get(1).toString();
			
			if ( !password.equals(pass) ) {
				connection.setMessage("230 Wrong password");
				dbConnection.doCommit();
				return true;
			}	
			
			
			// Vrsi update statusa korisnika, ip adrese, port, username
			String updateSQLCommand = "UPDATE tblUsers SET tblUsers.status='" + status + "', " +
									  "tblUsers.ip_address='" + ip_address + "', " +
									  "tblUsers.local_address='" + localAddress + "', " +
									  "tblUsers.port=" + port + 
									  " WHERE tblUsers.username='" + username + "'";
						
			dbConnection.doUpdateStatement(updateSQLCommand);	

			
			
			connection.setMessage("110 Login OK");

			connection.setUsername(username);
			
			activeConnections.put(username, connection);
			
			
			// mora da spava neko vreme, da bi omogucio da se podaci ispod pravilno
			// ucitaju i da se ispravno posalju stream-om
			//		try {
			//			Thread.sleep(200);
			//		}
			//		catch (InterruptedException ie) { ie.printStackTrace(); }
			
			String nickname = row.get(2).toString();
			String email = row.get(3).toString();
			String regDate = row.get(8).toString();
			String avatar = row.get(9).toString();
			
			StringBuffer loginData = new StringBuffer();
			loginData.append(nickname);
			loginData.append(" ");
			loginData.append(email);
			loginData.append(" ");
			loginData.append(regDate);
			loginData.append(" ");
			loginData.append(avatar);
			loginData.append(" ");
			loginData.append(ip_address);	// slanje globalne IP adrese klijentu (njegove)
			
			connection.setMessage(loginData.toString());
			
			dbConnection.clearDataStore();

			
			// Selektuje sve korisnike koji imaju na listi aktuelnog korisnika, a nisu
			// blokirani na korisnikovoj listi.
	
//			String SQLSelectQuery = "SELECT tblContacts.user_source " +
//			 	"FROM tblContacts " +
//			 	"WHERE  tblContacts.user_dest = '" + username + "' AND tblContacts.user_source NOT IN " +
//			   "(SELECT tblBlocks.user_dest FROM tblBlocks WHERE tblBlocks.user_source = '" + username + "');";		
	
			
			// Selektuje sve korisnike koje ovaj korisnik ima na listi, a nisu
			// blokirani na njegovoj listi.
			
			String SQLSelectQuery = "SELECT tblContacts.user_dest " +
				"FROM tblContacts " +
				"WHERE  tblContacts.user_source = '" + username + "' AND tblContacts.user_dest NOT IN " +
				"(SELECT tblBlocks.user_dest FROM tblBlocks WHERE tblBlocks.user_source = '" + username + "');";		

			
			dbConnection.doStatement(SQLSelectQuery);		
			
			// dobavljeni su nikovi korisnika koje treba obavestiti o statusu
			// korisnika
			
			ArrayList array = (ArrayList)dbConnection.data.clone();
			
			if(array.size() == 0) {
				dbConnection.doCommit();
				return true;
			}
				
			String message = "SERV_LOGIN " + username + " " + nickname + " " + email + " " +
								ip_address + " " + localAddress + " " + port + " " + status + " " +
								regDate + " " + avatar;
			
			// Obavestava sve korisnike o logovanju aktuelnog korisnika
			
			Iterator usersIterator = array.iterator();
			
			while ( usersIterator.hasNext() ) {
				
				// username korisnika 
				String user = ((Vector)usersIterator.next()).get(0).toString();
				
				ServerSocketConnection tempConnection = activeConnections.get(user);
				
				if (tempConnection != null) {
					tempConnection.setMessage(message);
//					System.out.println("Korisnik koji se obavestava o logovanju novog usera: " + user);
				}
			}
		
		} catch (SQLException e) {
			dbConnection.doRollBack();
			e.printStackTrace();
			return false;
		}
		
		System.out.println("--> User " + username + " has just logged in!");
		
		dbConnection.doCommit();
		
		return true;
	}	
	
}
